package com.gui.juc.future;

import com.gui.utils.Sleeper;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class CompletableFutureDemo2 {

    public static void main(String[] args) {

        ExecutorService threadPool = Executors.newFixedThreadPool(3);

        List<String> msgList = new ArrayList<>();
        log.debug("start");

        CompletableFuture<Void> task1 = CompletableFuture.supplyAsync(() -> {
            Sleeper.sleep(2);
            log.debug("task1 执行完毕");
            return "Node1 success";
        }, threadPool).thenAccept(msgList::add).exceptionally(e -> {
            log.error("Node1 monitor fail", e);
            msgList.add("Node1 error");
            return null;
        });

        CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> {
            Sleeper.sleep(3);
            log.debug("task2 执行完毕");
            return "Node2 success";
        }, threadPool).handle((result, e) -> {
            if (e == null) {
                msgList.add(result);
                return result;
            }
            msgList.add("Node2 error");
            return null;
        });


        CompletableFuture<Void> task3 = CompletableFuture.supplyAsync(() -> {
            Sleeper.sleep(4);
            log.debug("task3 执行完毕");
            return "Node3 success";
        }, threadPool).thenAccept(result -> {
            if (!result.equals("11")) {
                throw new NullPointerException();
            }
            msgList.add(result);
        }).exceptionally(e -> {
//            log.error("Node3 monitor fail", e);
            msgList.add("Node3 error");
            return null;
        });

        CompletableFuture.supplyAsync(() -> {
            return null;
        }).thenAccept(result -> {}).exceptionally(e -> {
            throw new RuntimeException(e);
        });

        CompletableFuture<Object> future = CompletableFuture.anyOf(task1, task2, task3);
        future.join();

        log.debug("result:{}", msgList);
        threadPool.shutdown();

    }
}
